package com.atguigu.java2;

import org.junit.Test;

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 方法引用的使用
 *     1.使用情境：
 *          当要传递给Lambda体的操作，已经有实现的方法了，可以使用方法引用
 *     2.方法引用，本质上就是lambda表达式，而lambda表达式作为函数接口的实例，所以方法引用，也是函数式接口的实例
 *
 *     3.使用格式： 类(或对象) :: 方法名
 *
 *     4.具体分为如下的三种情况：
 *           情况1    对象 :: 非静态方法
 *           情况2    类 :: 静态方法
 *           情况3    类 :: 非静态方法
 *
 *     5.方法引用使用的要求：要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的
 *       形参类型和返回值类型相同！(针对于情况1和情况2)
 *
 *       若Lambda参数列表中有2个参数，第一个参数是实例方法的调用者，而第二个参数是实例方法的参数时，可以使用方法引用的第三种情况
 *       类 :: 非静态方法
 *
 *       若Lambda参数列表中有1个参数，并且参数是实例方法的调用者，可以使用方法引用的第三种情况
 *       类 :: 非静态方法
 *
 *       以此类推
 *
 *
 * Created by shkstart.
 */
public class MethodRefTest {

	// 情况一：对象 :: 实例方法
	//Consumer中的void accept(T t)
	//PrintStream中的void println(T t)
	@Test
	public void test1() {
		Consumer<String> consumer = s -> System.out.println(s);
		consumer.accept("北京");
		System.out.println("********************************");
		PrintStream printStream = System.out;
		Consumer<String> consumer2 = printStream::println;
		consumer2.accept("beijing");
		
	}
	
	//Supplier中的T get()
	//Employee中的String getName()
	@Test
	public void test2() {
		Employee employee = new Employee(1001,"Tom",23,5600);
		Supplier<String> supplier = () -> employee.getName();
		System.out.println(supplier.get());
		System.out.println("*****************************************");
		Supplier<String> supplier2 = employee::getName;
		System.out.println(supplier2.get());
	}

	// 情况二：类 :: 静态方法
	//Comparator中的int compare(T t1,T t2)
	//Integer中的int compare(T t1,T t2)
	@Test
	public void test3() {
		Comparator<Integer> comparator = (t1,t2) ->Integer.compare(t1,t2);
		System.out.println(comparator.compare(12, 21));
		System.out.println("*******************************************");
		Comparator<Integer> comparator2 = Integer::compare;
		System.out.println(comparator2.compare(12,1));
	}
	
	//Function中的R apply(T t)
	//Math中的Long round(Double d)
	@Test
	public void test4() {
		Function<Double,Long> function = new Function<Double, Long>() {
			@Override
			public Long apply(Double d) {
				return Math.round(d);
			}
		};
		System.out.println("*****************************");
		Function<Double,Long> functio2 = d -> Math.round(d);
		System.out.println(functio2.apply(3.4));
		System.out.println("*****************************");
		Function<Double,Long> function3 = Math::round;
		System.out.println(function3.apply(5.6));

	}

	// 情况三：类 :: 实例方法 
	// Comparator中的int comapre(T t1,T t2)
	// String中的int t1.compareTo(t2)
	@Test
	public void test5() {
		Comparator<String> comparator = (s1,s2) ->s1.compareTo(s2);
		System.out.println(comparator.compare("abc", "abd"));
		System.out.println("*****************************");
		Comparator<String> comparator2 = String::compareTo;
		System.out.println(comparator2.compare("abd", "abm"));
	}

	//BiPredicate中的boolean test(T t1, T t2);
	//String中的boolean t1.equals(t2)
	@Test
	public void test6() {
		BiPredicate<String,String> biPredicate = (s1,s2) ->s1.equals(s2);
		System.out.println(biPredicate.test("abc", "abc"));
		System.out.println("*****************************");
		BiPredicate<String,String> biPredicate2 = String::equals;
		System.out.println(biPredicate2.test("abc", "abd"));

	}
	
	// Function中的R apply(T t)
	// Employee中的String getName();
	@Test
	public void test7() {
		Employee employee = new Employee(1001,"Tom",23,5600);
		Function<Employee,String> function = e -> e.getName();
		System.out.println(function.apply(employee));
		System.out.println("*****************************");
		Function<Employee,String> function2 = Employee::getName;
		System.out.println(function2.apply(employee));
	}

}
